package util

import (
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"

	"chainmaker.org/chainmaker/smarteditor/global"
	"github.com/88250/gulu"
)

const GoModFile = "go.mod"
const GoSumFile = "go.sum"

func OpenStdOutAndStdErr(cmd *exec.Cmd) (stdout, stderr io.ReadCloser, err error) {
	stdout, err = cmd.StdoutPipe()
	if nil != err {
		return nil, nil, err
	}

	stderr, err = cmd.StderrPipe()
	if nil != err {
		return nil, nil, err
	}
	return
}

func RunGoModInit(uid, path, userWorkspace, goPath, goRoot string, useDocker bool) (string, error) {
	modName := filepath.Base(path)
	cmd := exec.Command("go", "mod", "init", modName)
	cmd.Dir = path
	//非测试环境执行环境变量设置
	if global.TestnetEnv != true {
		setCmdEnvSimple(cmd, useDocker, goPath, goRoot)
	}
	outputBytes, err := cmd.CombinedOutput()
	return string(outputBytes), err
}

func RunGoModTidyInDirectoryDocker(directory string, useDocker bool, goPath, goRoot string) (string, error) {
	cmd := exec.Command("go", "mod", "tidy")
	cmd.Dir = directory
	//非测试环境执行环境变量设置
	if global.TestnetEnv != true {
		setCmdEnvSimple(cmd, useDocker, goPath, goRoot)
	}
	outputBytes, err := cmd.CombinedOutput()
	return string(outputBytes), err
}

func RunGoBuildInDirectoryDocker(directory string, targetName string, useDocker bool, goPath, goRoot string) (string, error) {
	cmd := exec.Command(filepath.Join(goRoot, "/bin/go"), "build", "-o", targetName, "-ldflags", "-s -w", "--tags", "crypto")
	cmd.Dir = directory
	//非测试环境执行环境变量设置
	if global.TestnetEnv != true {
		setCmdEnvSimple(cmd, useDocker, goPath, goRoot)
	}
	outputBytes, err := cmd.CombinedOutput()
	return string(outputBytes), err
}

func setCmdEnvSimple(cmd *exec.Cmd, docker bool, goPath, goRoot string) {
	cache, err := os.UserCacheDir()
	if nil != err {
		log.Warnf("Get user cache dir failed [" + err.Error() + "]")
		cache = os.TempDir()
	}
	goOs := runtime.GOOS
	goArch := runtime.GOARCH
	if docker {
		goOs = "linux"
		goArch = "amd64"
	}

	cmd.Env = append(cmd.Env,
		"CGO_ENABLED=1",
		"GOPROXY=https://goproxy.cn",
		"GO111MODULE=on",
		"GOPATH="+goPath,
		"GOOS="+goOs,
		"GOARCH="+goArch,
		"GOROOT="+goRoot,
		"GOCACHE="+cache,
		"GONOSUMDB=",
		"GOPRIVATE=",
		"PATH="+filepath.Join(goRoot, "bin")+":"+filepath.Join(goPath, "bin")+":"+os.Getenv("PATH"))

	if gulu.OS.IsWindows() {
		environ := os.Environ()
		for i := range environ {
			if strings.HasPrefix(environ[i], "GOROOT") {
				environ[i] = "GOROOT=" + goRoot
			}
		}
		cmd.Env = append(cmd.Env, environ...)
	} else {
		cmd.Env = append(cmd.Env, "LD_LIBRARY_PATH="+os.Getenv("LD_LIBRARY_PATH"))
	}
	log.Debugf("use docker %v,env %v", docker, cmd.Env)
}
